<!DOCTYPE html>
<html lang="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<head>
     <title>炸弹人v1.07 19.3.14 8:38 by:逆火狂飙 horn19782016@163.com</title>
	 <!--1.06版本启用了怪物跟随英雄的功能 -->
	 <!--1.07版本调整了怪物的寻路方式 -->
	 
	 <style>
	 #canvas{
		background:#ffffff;
		cursor:pointer;
		margin-left:10px;
		margin-top:10px;
		-webkit-box-shadow:3px 3px 6px rgba(0,0,0,0.5);
		-moz-box-shadow:3px 3px 6px rgba(0,0,0,0.5);
		box-shadow:3px 3px 6px rgba(0,0,0,0.5);
	 }
	 
	 #controls{
		margin-top:10px;
		margin-left:15px;
	 }
	 </style>
	 
    </head>

     <body onload="init()">
		<div id="controls">
			<input id='animateBtn' type='button' value='开始'/>
			<input id='playAgainBtn' type='button' value='再来一盘' style='visibility:hidden'/>
		</div>
	 
        <canvas id="canvas" width="160px" height="160px" >
            出现文字表示你的浏览器不支持HTML5
        </canvas>
     </body>
</html>
<script type="text/javascript">
<!--

// 暂停/开始游戏
animateBtn.onclick=function(e){
	paused=! paused;
	
	if(paused){
		animateBtn.value="开始";	
		screenMsg="Paused!";
	}else{	
		animateBtn.value="停止";
		window.requestAnimationFrame(animate); 
	}
}

// 重来游戏
playAgainBtn.onclick=function(e){
	init();
	playAgainBtn.style.visibility="hidden";
	animateBtn.value="停止";
	paused=false;
	window.requestAnimationFrame(animate); 
}

var paused=true;// 是否暂停
var BL=32;		// Block length,边长
var ctx;		// 绘图环境
var terrain;	// 地形
var hero;		// 英雄/主角
var monsterMng;	// 怪物管理类
var bombs;		// 炸弹数组
var fires;		// 火焰数组
var screenMsg;	// 显示在屏幕中央的话语
var bonusMng; 	// 奖励管理类

function init(){
	// init Canvas
	var canvas=document.getElementById('canvas');
	canvas.width =40*BL;
	canvas.height=18*BL;
	ctx=canvas.getContext('2d');
	
	terrain=new Terrain();
	hero=new Hero();
	monsterMng=new MonsterMng();
	bombs=new Array();
	fires=new Array();
	
	bonusMng=new BonusMng();
		
	// 响应键盘事件
	canvas.addEventListener('keydown', doKeyDown, true);
	canvas.focus();  
	window.addEventListener('keydown', doKeyDown, true);
};

//------------------------------------
// 响应键盘事件
//------------------------------------
function doKeyDown(e) {
	var keyID = e.keyCode ? e.keyCode :e.which;
	if(keyID === 38 || keyID === 87)  { // up arrow and W
		hero.move('up');
		e.preventDefault();
	}
	if(keyID === 39 || keyID === 68)  { // right arrow and D
		hero.move('right');
		e.preventDefault();
	}
	if(keyID === 40 || keyID === 83)  { // down arrow and S
		hero.move('down');
		e.preventDefault();
	}
	if(keyID === 37 || keyID === 65)  { // left arrow and A
		hero.move('left');
		e.preventDefault();
	}

	if(keyID === 32 )  { // SpaceBar
		var b=new Bomb(hero.x,hero.y,hero.explosionRange);
		bombs.push(b);
		//console.log('arrows.length='+arrows.length);
		e.preventDefault();
	}
}

//------------------------------------
// 更新各实例状态
//------------------------------------
function update(){
	monsterMng.move();
	
	var heroX=parseInt(hero.x/BL,10);
    var heroY=parseInt(hero.y/BL,10);
        
    // 看英雄碰到怪物没
    if(monsterMng.isTouched(heroX,heroY)){
        hero.setDead();
    }
	
	// 计算爆炸范围
	var explosions=[];
	for(var i=0;i<fires.length;i++){
		var f=fires[i];
		
		if(f.lifeTime>0){
			explosions.push(new Point(f.x,f.y));
		}
	}
	
	// 爆炸对怪物的伤害
	monsterMng.makeDeadInRange(explosions);
	
	// 爆炸对英雄的伤害
	hero.makeDeadInRange(explosions);
	
	// 奖励
	bonusMng.enlargeExplosionRange(hero);

	// 让怪物吃奖励提升速度
	var aliveMonsters=monsterMng.getAliveMonsters();
	bonusMng.raiseSpeed(aliveMonsters);
    
    // 游戏结束条件
    if(hero.alive==false){ // 英雄死亡
		paused=true;
		screenMsg="You lost!";
		animateBtn.value="开始";
		playAgainBtn.style.visibility="visible";
    }
    
	// 游戏胜利条件
    if(monsterMng.noMonster() && hero.alive==true){ // 怪物全清除 及 英雄存活
		paused=true;
		screenMsg="You win!";
		animateBtn.value="开始";
		playAgainBtn.style.visibility="visible";
    }
}

//------------------------------------
// 在ctx里画出各实例
//------------------------------------
function draw(){
	// Clear Canvas
	ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
	ctx.fillStyle="#ffffff";
	ctx.fillRect(0,0,ctx.canvas.width,ctx.canvas.height);
	
	terrain.paint(ctx);	// 画地形
	bonusMng.paint(ctx);// 画奖励
	
	monsterMng.paint(ctx);
	hero.paint(ctx);	// 画英雄
	
	// 画炸弹
	for(var i=0;i<bombs.length;i++){
		var b=bombs[i];
		b.paint(ctx);
	}
	
	// 画火焰
	for(var i=0;i<fires.length;i++){
		var b=fires[i];
		b.paint(ctx);
	}
}

//------------------------------------
// 运行动画
//------------------------------------
function animate(){
	if(!paused){
		update();
		draw();
	    window.requestAnimationFrame(animate); /// 让浏览器自行决定帧速率
	}else{
		ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
		ctx.font="bold 48px 宋体";
		ctx.fillStyle='Red';
		ctx.fillText(screenMsg,ctx.canvas.width/2,ctx.canvas.height/2);
	}
}

//------------------------------------
//  常规函数:角度得到弧度
//------------------------------------
function getRad(degree){
    return degree/180*Math.PI;
}

//------------------------------------------------------------
// 常规函数:得到0到N（包括N）的随机整数
// 如果要得到数组里面的一个要把数组长度减一
//------------------------------------------------------------
function getRndFromZeroToN(n){
	return Math.floor(Math.random()*(n+1));
}

//------------------------------------------------------------
// 常规函数:得到lowerLimit到upperlimit（包括端点值）的随机整数
//------------------------------------------------------------
function getRndBetween(lowerLimit,upperlimit){
	return Math.floor(Math.random()*(upperlimit-lowerLimit+1))+lowerLimit;
}

//---------------------------------------------------地形类定义开始------------------------------------------------------------------->>
Terrain=function(){
	this.files=["road.png",       	//  0
				"tree.png",			//  1
				"farmerHouse.png",	//  2
				"twoBuilding.png",	//  3
				"threeBuilding.png",//  4
				"bank.png",			//  5
				"villa.png",		//  6
				"blackWhiteRoad.png",];		//  7
	
	/*this.maps=new Array(
        [0,0,0,0,0],
        [0,0,1,0,0],
        [0,0,0,0,0],
        [0,2,0,0,0],
        [0,0,0,3,0],
    );*/
	this.maps=new Array(
		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],
		[0,1,2,1,2,1,0,1,2,1,0,0,1,1,1,1,1,0,],
		[0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,1,0,],
		[0,1,2,1,2,1,0,1,2,1,0,0,5,0,0,3,1,0,],
		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,1,0,],
		[0,1,2,1,2,1,0,1,2,1,0,0,3,3,3,3,1,0,],
		[0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,],
		[0,1,2,1,2,1,0,1,2,1,0,0,0,0,0,0,0,0,],
		[0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,],
		[0,1,2,1,2,1,0,1,2,1,0,1,4,4,4,4,1,0,],
		[0,0,0,0,0,0,0,0,0,0,0,1,4,0,0,0,1,0,],
		[0,1,2,1,2,1,0,1,2,1,0,1,5,0,0,0,0,0,],
		[0,0,0,0,0,0,0,0,0,0,0,1,4,0,0,0,1,0,],
		[0,1,2,1,2,1,0,1,2,1,0,1,4,4,4,4,1,0,],
		[0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,],
		[0,1,2,1,2,1,0,1,2,1,0,0,0,0,0,0,0,0,],
		[0,0,0,0,0,0,0,0,0,0,0,1,6,1,6,1,6,0,],
		[0,1,2,1,2,1,0,1,2,1,0,6,0,0,0,0,1,0,],
		[0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,6,0,],
		[0,1,2,1,2,1,0,1,2,1,0,0,0,5,0,0,1,0,],
		[0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,6,0,],
		[0,1,2,1,2,1,0,1,2,1,0,6,0,0,0,0,1,0,],
		[0,0,0,0,0,0,0,0,0,0,0,1,6,1,6,1,6,0,],
		[0,1,2,1,2,1,0,1,2,1,0,0,0,0,0,0,0,0,],
		[0,0,0,0,0,0,0,0,0,0,0,1,6,1,6,1,0,0,],
		[0,1,2,1,2,1,0,1,2,1,0,0,0,0,0,0,0,0,],
		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],
		[0,1,2,1,2,1,0,1,2,1,6,1,0,0,0,0,0,0,],
		[0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,],
		[0,1,2,1,2,1,0,1,2,1,6,1,0,4,0,0,0,0,],
		[0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,3,0,0,],
		[0,1,2,1,2,1,0,1,2,1,6,1,0,0,0,4,0,0,],
		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,],
		[0,1,2,1,2,1,0,1,2,1,6,1,0,0,0,0,0,0,],
		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],
		[0,1,2,1,2,1,0,1,2,1,0,0,0,0,0,0,0,0,],
		[0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,0,0,],
		[0,1,2,1,2,1,0,1,2,1,0,2,2,2,0,2,2,2,],
		[0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,],
		[0,1,2,1,2,1,0,1,2,1,0,2,0,0,0,0,0,2,],
	);
}
Terrain.prototype={
	files:[],
    maps:[],
    
    // method
    paint:function(ctx){
		for(var i=0;i<this.maps.length;i++){
			var arr=this.maps[i];
			
			for(var j=0;j<arr.length;j++){
				var value=arr[j];
				
				var img=new Image();
				img.src=this.files[value];
				
				ctx.drawImage(img,i*BL,j*BL);
			}
		}
    },
	
	// 是否有障碍
	hasObstacle:function(i,j){
		if(i<0 || i>=this.maps.length){
			return true;
		}
		var arr=this.maps[i];
		if(j<0 || j>=arr.length){
			return true;
		}
		var value=arr[j];
		if(value==0){
			return false;
		}else{
			return true;
		}
	},

	getValue:function(i,j){
		if(i<0 || i>=this.maps.length){
			return undefined;
		}
		var arr=this.maps[i];
		if(j<0 || j>=arr.length){
			return undefined;
		}
		var value=arr[j];
		return value;
	},
	
	setValue:function(i,j,value){
		if(i<0 || i>=this.maps.length){
			return undefined;
		}
		var arr=this.maps[i];
		if(j<0 || j>=arr.length){
			return undefined;
		}
		arr[j]=value;
	},
	
	// 取得空点数组
	getEmptyPoints:function(count){
		var allEmptyPoints=[];
	
		for(var i=0;i<this.maps.length;i++){
			var arr=this.maps[i];
			
			for(var j=0;j<arr.length;j++){
				var value=arr[j];
				
				if(value==0){
					allEmptyPoints.push(new Point(i*BL,j*BL));
				}
			}
		}
		
		var retval=[];
		//var n=allEmptyPoints.length;
		//console.log("allEmptyPoints.length="+allEmptyPoints.length);
		for(var i=0;i<count;i++){
			var seed=this.getRndFromZeroToN(allEmptyPoints.length-1);
			var p=allEmptyPoints[seed];
			retval.push(p);
		}
		
		return retval;
	},

	//------------------------------------------------------------
	// 得到0到N（包括N）的随机整数
	// 如果要得到数组里面的一个要把数组长度减一
	//------------------------------------------------------------
	getRndFromZeroToN:function(n){
		return Math.floor(Math.random()*(n+1));
	},
}
//---------------------------------------------------地形类定义结束-------------------------------------------------------------------<<

//---------------------------------------------------英雄类定义开始------------------------------------------------------------------->>
Hero=function(){
	this.pngs=[
		{left:0,top:10,width:40,height:40},
		{left:0,top:68,width:40,height:40},
		{left:0,top:123,width:40,height:40},
		{left:0,top:180,width:40,height:40},
	];
}
Hero.prototype={
	pngs:[],
    x:19*BL,
	y:10*BL,
	xTo:19*BL,
	yTo:10*BL,
	step:BL,
	direction:'up',		// 面向
	alive:true,			// 是否活着
	explosionRange:4,	// 爆炸范围
    
    setDead:function(){
        //console.log('Hero dead');
        this.alive=false;
    },
    
    paint:function(ctx){
		var img=new Image();
		img.src='bowman.png';
		
		var index=0;
		if(this.direction=='up'){
			index=3;
		}
		if(this.direction=='down'){
			index=0;
		}
		if(this.direction=='left'){
			index=1;
		}
		if(this.direction=='right'){
			index=2;
		}
		var pos=this.pngs[index];
		ctx.drawImage(img,pos.left,pos.top,pos.width,pos.height,this.x,this.y,32,32);
    },
	
	move:function(direction){
		this.direction=direction;
		
		if(this.direction=='up'){
			this.yTo-=this.step;
		}
		if(this.direction=='down'){
			this.yTo+=this.step;
		}
		if(this.direction=='left'){
			this.xTo-=this.step;
		}
		if(this.direction=='right'){
			this.xTo+=this.step;
		}
		
		if(terrain.getValue(this.xTo/this.step,this.yTo/this.step)==0){
			this.x=this.xTo;
			this.y=this.yTo;
		}else{
			this.xTo=this.x;
			this.yTo=this.y;
		}
	},
	
	// 爆炸火焰一样对英雄造成伤害
	makeDeadInRange:function(explosions){
	   for(var j=0;j<explosions.length;j++){
			var point=explosions[j];

			//  爆炸范围判断符合实际情况
			var xx=Math.pow((this.x-point.x),2);
			var yy=Math.pow((this.y-point.y),2);
			var distance=Math.sqrt(xx+ yy);
			if(distance<BL/2){
				this.setDead();
			}
	   }
	},
}
//---------------------------------------------------英雄类定义结束-------------------------------------------------------------------<<


//---------------------------------------------------点类定义开始------------------------------------------------------------------->>
Point=function(x,y){
	this.x=x;
	this.y=y;
}
Point.prototype={
	x:0,			// 横坐标
	y:0,			// 纵坐标
}
//---------------------------------------------------点类定义结束-------------------------------------------------------------------<<

//---------------------------------------------------点类定义开始------------------------------------------------------------------->>
Target=function(x,y,direction){
	this.x=x;
	this.y=y;
	this.direction=direction;
}
Target.prototype={
	x:0,			// 横坐标
	y:0,			// 纵坐标
	direction:'',	// 方向
}
//---------------------------------------------------点类定义结束-------------------------------------------------------------------<<


//---------------------------------------------------怪物类定义开始------------------------------------------------------------------->>
Monster=function(x,y){
	this.x=x;
	this.y=y;
	steps=[1,2,4,8];
	
	var rndSeed=this.getRndFromZeroToN(steps.length-1);
	
	this.step=steps[rndSeed];
	
	this.files=["monster1.png",       		//  0
				"monster1Dead.png",			//  1
				"monster2.png",       		//  2
				"monster2Dead.png",			//  3
				"monster3.png",       		//  4
				"monster3Dead.png",			//  5
				"monster4.png",       		//  6
				"monster4Dead.png",			//  7
				];	
}
Monster.prototype={
	x:0,			// 横坐标，乘以32等于真正的横坐标
	y:0,			// 纵坐标，乘以32等于真正的纵坐标
	step:1,			// 行走速度
	steps:[],		// 行走速度数组
	direction:'',	// 方向
	files:[],		// 显示图片
	alive:true,		// 是否活着
	thinking:true,	// 是否在找路
	targetPoint:[],
    
	// 设置死亡
	setDead:function(){
		this.alive=false;
    },
	
	// 成倍提升速度
	doubleStep:function(){
		this.step*=2;
		
		if(this.step>=512){
			this.step=512;
		}
    },
	
	// 移动
	move:function(){
		if(this.alive){
			if(this.thinking==true){
				// 思考下一步往哪里走
				targetPoint=null;
				
				// 选择偏向英雄的方向
				var xDiff=this.x-hero.x;
				var yDiff=this.y-hero.y;
												
				var emptyPlaces=[];
				var monsterX=parseInt(this.x/BL,10);
				var monsterY=parseInt(this.y/BL,10);
				var pointsTmp=[];
				var targets=[];
				
				//if(xDiff>=0){
					// 左边方格
					for(var i=1;i<=this.step;i++){
						var hasObstacle=terrain.hasObstacle(monsterX-i,monsterY);
						if(hasObstacle==false){
							pointsTmp.push(new Point(monsterX-i,monsterY));
						}else{
							break;
						}
					}
					if(pointsTmp.length>0){
						var p=pointsTmp[pointsTmp.length-1];
						emptyPlaces.push(new Target(p.x,p.y,"Left"));
						pointsTmp=[];
					}
				//}

				//if(xDiff<0){
					// 右边方格
					for(var i=1;i<=this.step;i++){
						var hasObstacle=terrain.hasObstacle(monsterX+i,monsterY);
						if(hasObstacle==false){
							pointsTmp.push(new Point(monsterX+i,monsterY));
						}else{
							break;
						}
					}
					if(pointsTmp.length>0){
						var p=pointsTmp[pointsTmp.length-1];
						emptyPlaces.push(new Target(p.x,p.y,"Right"));
						pointsTmp=[];
					}
				//}
				
				//if(yDiff>=0){
					// 上边方格
					for(var i=1;i<=this.step;i++){
						var hasObstacle=terrain.hasObstacle(monsterX,monsterY-i);
						if(hasObstacle==false){
							pointsTmp.push(new Point(monsterX,monsterY-1));
						}else{
							break;
						}
					}
					if(pointsTmp.length>0){
						var p=pointsTmp[pointsTmp.length-1];
						emptyPlaces.push(new Target(p.x,p.y,"Up"));
						pointsTmp=[];
					}
				//}
				
				//if(yDiff<0){
					// 下边方格
					for(var i=1;i<=this.step;i++){
						var hasObstacle=terrain.hasObstacle(monsterX,monsterY+i);
						if(hasObstacle==false){
							pointsTmp.push(new Point(monsterX,monsterY+1));
						}else{
							break;
						}
					}
					if(pointsTmp.length>0){
						var p=pointsTmp[pointsTmp.length-1];
						emptyPlaces.push(new Target(p.x,p.y,"Down"));
						pointsTmp=[];
					}
				//}
				
				
				if(xDiff>=0){
					for(var i=0;i<emptyPlaces;i++){
						var t=emptyPlaces[i];
						if(t.direction=='Left'){
							targets.push(t);
						}
					}
				}else{
					for(var i=0;i<emptyPlaces;i++){
						var t=emptyPlaces[i];
						if(t.direction=='Right'){
							targets.push(t);
						}
					}
				}
				
				if(yDiff>=0){
					for(var i=0;i<emptyPlaces;i++){
						var t=emptyPlaces[i];
						if(t.direction=='Up'){
							targets.push(t);
						}
					}
				}else{
					for(var i=0;i<emptyPlaces;i++){
						var t=emptyPlaces[i];
						if(t.direction=='Down'){
							targets.push(t);
						}
					}
				}
					
				if(targets.length>0){
					// 如果能跟主角行走，则从目标中选择方向
					var rndSeed=this.getRndFromZeroToN(targets.length-1);
					var t=targets[rndSeed];
					this.targetPoint.x=t.x;
					this.targetPoint.y=t.y;
				}else{
					//  如果不能跟主角行走，则从可寻找的方向中选择一个方向
					var rndSeed=this.getRndFromZeroToN(emptyPlaces.length-1);
					this.targetPoint=emptyPlaces[rndSeed];
				}
				
			
				
				
				
				//console.log(targetPoint);
				
				if(this.targetPoint!=null){
					//console.log(this.targetPoint);
					this.thinking=false;
				}				
			}else{
				// 思考好了就走
				var targetX=this.targetPoint.x*BL;
				var targetY=this.targetPoint.y*BL;
				
				//console.log(this.targetPoint,this.x,this.y);
				
				if(targetX==this.x && targetY<this.y){
					this.y-=this.step;
				}
				if(targetX==this.x && targetY>this.y){
					this.y+=this.step;
				}
				if(targetX<this.x && targetY==this.y){
					this.x-=this.step;
				}
				if(targetX>this.x && targetY==this.y){
					this.x+=this.step;
				}
				if(targetX==this.x && targetY==this.y){
					this.thinking=true;
				}
			}
			
		}
	},
	
	//------------------------------------------------------------
	// 得到0到N（包括N）的随机整数
	// 如果要得到数组里面的一个要把数组长度减一
	//------------------------------------------------------------
	getRndFromZeroToN:function(n){
		return Math.floor(Math.random()*(n+1));
	},

	// 画怪物
    paint:function(ctx){
		var img=new Image();
		
		if(this.alive==true && this.step==1){
			img.src=this.files[0];
		}
		if(this.alive==false && this.step==1){
			img.src=this.files[1];
		}
		if(this.alive==true && this.step==2){
			img.src=this.files[2];
		}
		if(this.alive==false && this.step==2){
			img.src=this.files[3];
		}
		if(this.alive==true && this.step==4){
			img.src=this.files[4];
		}
		if(this.alive==false && this.step==4){
			img.src=this.files[5];
		}
		if(this.alive==true && this.step>=8){
			img.src=this.files[6];
		}
		if(this.alive==false && this.step>=8){
			img.src=this.files[7];
		}
		
		ctx.drawImage(img,this.x,this.y);
    },
	
}
//---------------------------------------------------怪物类定义结束-------------------------------------------------------------------<<

//---------------------------------------------------怪物管理类定义开始------------------------------------------------------------------->>
MonsterMng=function(){
	this.addMonster(9);
}
MonsterMng.prototype={
    monsters:[],
    
    // 生成怪物,测试用
    generateMonsters:function(){
        this.monsters=new Array();
        this.monsters.push(new Monster(1*BL,1*BL,3));
        this.monsters.push(new Monster(1*BL,10*BL,3));
        this.monsters.push(new Monster(16*BL,16*BL,2));
        this.monsters.push(new Monster(10*BL,13*BL,5));
        this.monsters.push(new Monster(10*BL,10*BL,6));
		this.monsters.push(new Monster(24*BL,1*BL,1));
    },
    
    // 画怪物
    paint:function(ctx){
		
        for(var i=0;i<this.monsters.length;i++){
            var m=this.monsters[i];
            m.paint(ctx);
        }
		
		// 写怪物数目
		ctx.textAlign = 'left';
        ctx.textBaseline = 'middle';
		ctx.font="bold 24px 宋体";
		ctx.fillStyle='maroon';
		ctx.fillText("Monsters:"+this.getAliveMonsterNum(),ctx.canvas.width-5*BL,BL/2);
    },
	
	// 让怪物移动
	move:function(ctx){
        for(var i=0;i<this.monsters.length;i++){
            var m=this.monsters[i];
            m.move();
        }
    },
	
	// 得到活着的怪兽数量
	getAliveMonsterNum:function(){
		var count=0;
		
		for(var i=0;i<this.monsters.length;i++){
            var m=this.monsters[i];
            if(m.alive){
				count++;
			}
        }
		
		return count;
	},
	
	// 得到活着的怪兽数组
	getAliveMonsters:function(ctx){
		var arr=[];
		
        for(var i=0;i<this.monsters.length;i++){
            var m=this.monsters[i];
            if(m.alive==true){
				arr.push(m);
			}
        }
		
		return arr;
    },
    
    // 判断怪物还是否存在
    hasMonster:function(){
		var count=this.getAliveMonsterNum();
		
        return count==0;
    },
    
    // 看英雄是否碰到怪物
    isTouched:function(heroX,heroY){
        for(var i=0;i<this.monsters.length;i++){
            var monster=this.monsters[i];

            var monsterX=parseInt(monster.x/BL,10);
            var monsterY=parseInt(monster.y/BL,10);

            //console.log('isTouched',heroX,heroY,monsterX,monsterY);
            if(heroX==monsterX && heroY==monsterY && monster.alive==true){
                //console.log('touched',heroX,heroY,monsterX,monsterY);
                return true;
            }
        }
        
        return false;
    },
    
    // 看有没有怪物了
    noMonster:function(heroX,heroY){
        var count=0;
    
        for(var i=0;i<this.monsters.length;i++){
            var monster=this.monsters[i];

            if(monster.alive){
                count++;
            }
        }
        
        return count==0;
    },
	
	// 将爆炸范围内的怪物致死
	makeDeadInRange:function(explosions){
		//console.log(explosions);
		for(var i=0;i<this.monsters.length;i++){
            var monster=this.monsters[i];

            if(monster.alive){
               for(var j=0;j<explosions.length;j++){
					var point=explosions[j];
					//console.log(monster.x,monster.y,point.x,point.y);
					/*if(monster.x==point.x && monster.y==point.y){  // 精确判断不符合实际情况
						monster.setDead();
					}*/
					
					// 范围判断符合实际情况
					var xx=Math.pow((monster.x-point.x),2);
					var yy=Math.pow((monster.y-point.y),2);
					var distance=Math.sqrt(xx+ yy);
					if(distance<BL/2){
						monster.setDead();
					}
			   }
            }
        }
	},
	
	// 添加怪物
	addMonster:function(n){
		this.monsters=new Array();
		var points=terrain.getEmptyPoints(n);
		
		for(var i=0;i<points.length;i++){
			var p=points[i];
			
			this.monsters.push(new Monster(p.x,p.y));
			//this.bonusArr.push(new Bonus(p.x,p.y));
		}
		
		console.log(this.monsters);
	},
}
//---------------------------------------------------怪物管理类定义结束-------------------------------------------------------------------<<

//---------------------------------------------------炸弹类定义开始------------------------------------------------------------------->>
Bomb=function(x,y,explosionRange){
	this.x=x;
	this.y=y;
	
	// 放下炸弹，让其起障碍作用
	var bombX=parseInt(this.x/BL,10);
    var bombY=parseInt(this.y/BL,10);
	terrain.setValue(bombX,bombY,7);
	
	this.explosionRange=explosionRange;
	this.files=['bomb1.png','bomb2.png','bomb3.png','bomb4.png'];
}
Bomb.prototype={
	x:0,			// 横坐标
	y:0,			// 纵坐标
	files:[],		// 表现炸弹的图片
	level:0,		// 等级，越高越解决爆炸
	exploded:false, // 是否爆炸
	explosionRange:1,// 爆炸范围
	
	// 画炸弹
    paint:function(ctx){
		if(this.exploded==false){
			var img=new Image();
			this.level+=0.75;
			
			if(this.level<20){
				img.src=this.files[0];
			}else if(this.level>=20 && this.level<40){
				img.src=this.files[1];
			}else if(this.level>=40 && this.level<60){
				img.src=this.files[2];
			}else if(this.level>=60 && this.level<80){
				img.src=this.files[3];
			}else if(this.level>=80 && this.level<100){
				img.src=this.files[4];
			}else if(this.level>=100){
				// 起爆
				this.exploded=true;
				
				// 爆炸完毕，让其恢复通行
				var bombX=parseInt(this.x/BL,10);
			    var bombY=parseInt(this.y/BL,10);
				terrain.setValue(bombX,bombY,0);
				
				// 创建火焰对象
				this.makeFire();
			}

			ctx.drawImage(img,this.x,this.y);
		}
    },
	
	// 制造火焰
	makeFire:function(){
		var emptyPlaces=[];
		var bombX=parseInt(this.x/BL,10);
		var bombY=parseInt(this.y/BL,10);
		//console.log(bombX,bombY);

		// Left
		for(var i=1;i<=this.explosionRange;i++){
			var hasObstacle=terrain.hasObstacle(bombX-i,bombY);
			if(hasObstacle==false){
				emptyPlaces.push(new Point(bombX-i,bombY));
			}else{
				break;
			}
		}
		
		// Right
		for(var i=1;i<=this.explosionRange;i++){
			var hasObstacle=terrain.hasObstacle(bombX+i,bombY);
			if(hasObstacle==false){
				emptyPlaces.push(new Point(bombX+i,bombY));
			}else{
				break;
			}
		}
		
		// Up
		for(var i=1;i<=this.explosionRange;i++){
			var hasObstacle=terrain.hasObstacle(bombX,bombY-i);
			if(hasObstacle==false){
				emptyPlaces.push(new Point(bombX,bombY-i));
			}else{
				break;
			}
		}
		
		// down
		for(var i=1;i<=this.explosionRange;i++){
			var hasObstacle=terrain.hasObstacle(bombX,bombY+i);
			if(hasObstacle==false){
				emptyPlaces.push(new Point(bombX,bombY+i));
			}else{
				break;
			}
		}
		
		// Center
		var hasObstacle=terrain.hasObstacle(bombX,bombY);
		if(hasObstacle==false){
			emptyPlaces.push(new Point(bombX,bombY));
		}
		
		//console.log(emptyPlaces);
		// 添加火焰对象
		for(var i=0;i<emptyPlaces.length;i++){
			var p=emptyPlaces[i];
			
			var f=new Fire(p.x*BL,p.y*BL);
			fires.push(f);
		}
	},
}
//---------------------------------------------------炸弹类定义结束-------------------------------------------------------------------<<

//---------------------------------------------------火焰类定义开始------------------------------------------------------------------->>
Fire=function(x,y){
	this.x=x;
	this.y=y;
	this.files=['fire1.png','fire2.png'];
}
Fire.prototype={
	x:0,			// 横坐标
	y:0,			// 纵坐标
	files:[],		// 火焰图片
	lifeTime:50,	// 显示时间
	
	paint:function(ctx){
		if(this.lifeTime>0){
			this.lifeTime--;
			
			var img=new Image();
			
			if(this.lifeTime>25){
				img.src=this.files[0];
			}else{
				img.src=this.files[1];
			}
		
			ctx.drawImage(img,this.x,this.y);
		}
	},
}
//---------------------------------------------------火焰类定义结束-------------------------------------------------------------------<<

//---------------------------------------------------奖励类定义开始------------------------------------------------------------------->>
Bonus=function(x,y){
	this.x=x;
	this.y=y;
	this.files=['bonus.png','bonus1.png'];
}
Bonus.prototype={
	x:0,			// 横坐标
	y:0,			// 纵坐标
	files:[],		// 图片
	used:false,		// 是否使用过
	index:0,		// 作为两张图片交替显示的取舍
	
	paint:function(ctx){
		if(this.used==false){
		
			var img=new Image();
			img.src=this.files[0];
			
			this.index++;
			if(this.index>400){
				this.index=0;
			}
			
			if(this.index<200){
				img.src=this.files[1];
			}else{
				img.src=this.files[0];
			}
					
			ctx.drawImage(img,this.x,this.y);
		}
	},
}
//---------------------------------------------------奖励类定义结束-------------------------------------------------------------------<<

//---------------------------------------------------奖励管理类定义开始------------------------------------------------------------------->>
BonusMng=function(x,y){
	this.bonusArr=new Array();
	
	this.addBonus(2);
}
BonusMng.prototype={
	bonusArr:[],		// 奖励数组

	paint:function(ctx){
		for(var i=0;i<this.bonusArr.length;i++){
			var b=this.bonusArr[i];
			b.paint(ctx);
		}
	},
	
	// 提升英雄的爆炸范围
	enlargeExplosionRange:function(hero){
		for(var i=0;i<this.bonusArr.length;i++){
			var b=this.bonusArr[i];
			
			if(b.used==false && b.x==hero.x && b.y==hero.y){
				hero.explosionRange+=1;
				b.used=true;
				break;
				
				
			}
		}
		
		this.refresh();
	},
	
	// 提升怪物速度
	raiseSpeed:function(monsters){
		for(var i=0;i<monsters.length;i++){
			var monster=monsters[i];
			
			if(monster.alive==true){
				for(var j=0;j<this.bonusArr.length;j++){
					var b=this.bonusArr[j];
					
					if(b.used==false && b.x==monster.x && b.y==monster.y){
						monster.doubleStep();
						b.used=true;
						
						console.log(this.bonusArr);
						
					}
				}
			}
		}
		
		this.refresh();
	},
	
	// 更新bonus
	refresh:function(){
		var count=0;
		for(var i=0;i<this.bonusArr.length;i++){
			var b=this.bonusArr[i];
			
			if(b.used==false){
				count++;// 统计未被使用的bonus个数
			}
		}
		
		if(count==0){
			this.addBonus(1);// 如果没有bonus了再动态加几个
		}
	},
	
	addBonus:function(n){
		var points=terrain.getEmptyPoints(n);
		
		for(var i=0;i<points.length;i++){
			var p=points[i];
			this.bonusArr.push(new Bonus(p.x,p.y));
		}
	},
}
//---------------------------------------------------奖励管理类定义结束-------------------------------------------------------------------<<
//-->
</script>